package org.shiro.demo.util;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * 
 * @Description: TODO
 * @author : Tian (Ten)
 * @date ： 2015-1-20 上午11:31:08
 */
public class WeixinPayClient {
	public HttpURLConnection getCon() {
		return conn;
	}

	public static String REQ_METHOD_GET = "GET";
	public static String REQ_METHOD_POST = "POST";
	// public static String REQ_METHOD_HEAD = "HEAD";
	// public static String REQ_METHOD_PUT = "OPTIONS";
	// public static String REQ_METHOD_TRACE = "TRACE";

	// 请求地址
	private String address = "https://api.sms.mob.com/sms/verify";

	// 请求参数
	private List<String> params = new ArrayList<String>();

	// 链接超时时间
	public int conn_timeout = 10000;

	// 读取超时
	public int read_timeout = 10000;

	// 请求方式
	public String method = REQ_METHOD_POST;

	private HttpURLConnection conn;

//	private static WeixinPayClient mobClient;

	public WeixinPayClient(String address) throws KeyManagementException, NoSuchAlgorithmException, IOException {
		this.address = address;
		this.conn = build();
	}

	/**
	 * 上传数据
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public String post(String data) throws Exception {
		return requestData(address, data);
	}

	/**
	 * 上传数据
	 * 
	 * @return
	 * @throws Exception
	 */
	public String post() throws Exception {
		String pstr = getParams();
		return post(pstr);
	}

	/**
	 * 获得kv 参数
	 * 
	 * @return k1=val&k2=val2
	 */
	private String getParams() {
		StringBuffer buffer = new StringBuffer();
		boolean first = true;
		for (String kv : params) {
			if (first)
				first = false;
			else
				buffer.append("&");

			buffer.append(kv);
		}
		return buffer.toString();
	}

	/**
	 * 发起https 请求
	 * 
	 * @param address
	 * @param m
	 * @return
	 * @throws Exception
	 */
	private String requestData(String address, String params) throws Exception {

		// set params ;post params
		if (params != null) {
			conn.setDoOutput(true);
			DataOutputStream out = new DataOutputStream(conn.getOutputStream());
			out.write(params.getBytes(Charset.forName("UTF-8")));
			out.flush();
			out.close();
		}
		conn.connect();
		// get result
		try {
			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				String result = parsRtn(conn.getInputStream());
				return result;
			} else {
				throw new Exception(conn.getResponseCode() + " " + conn.getResponseMessage());
			}
		} catch (Exception e) {
			throw e;
		} finally {
			// 见
			//
			// I think you should always call disconnect in the finally block.
			// The android documentation notes that you should use disconnect
			// which facilitates the reuse of the underlying socket if possible.
			// From
			// http://developer.android.com/reference/java/net/HttpURLConnection.html
			//
			// "Disconnect. Once the response body has been read, the HttpURLConnection should be closed by calling disconnect(). Disconnecting releases the resources held by a connection so they may be closed or reused."
			conn.disconnect();// 释放资源，这样他能被重用
		}

	}

	private HttpURLConnection build() throws NoSuchAlgorithmException, KeyManagementException, IOException {

//		HttpURLConnection conn = null;
		// Create a trust manager that does not validate certificate chains
		TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}

			public void checkClientTrusted(X509Certificate[] certs, String authType) {
			}

			public void checkServerTrusted(X509Certificate[] certs, String authType) {
			}
		} };

		// Install the all-trusting trust manager
		SSLContext sc = SSLContext.getInstance("TLS");
		sc.init(null, trustAllCerts, new SecureRandom());

		// ip host verify
		HostnameVerifier hv = new HostnameVerifier() {
			public boolean verify(String urlHostName, SSLSession session) {
				return urlHostName.equals(session.getPeerHost());
			}
		};

		// set ip host verify
		HttpsURLConnection.setDefaultHostnameVerifier(hv);

		HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

		URL url = new URL(address);
		conn = (HttpURLConnection) url.openConnection();

		conn.setRequestMethod(method);// POST
		conn.setConnectTimeout(conn_timeout);
		conn.setReadTimeout(read_timeout);

		// 设置一些参数。
		conn.setDoOutput(true);
		conn.setRequestProperty("Pragma:", "no-cache");
		conn.setRequestProperty("Cache-Control", "no-cache");
		conn.setRequestProperty("Content-Type", "text/xml");
		return conn;
	}

	public void addRequestProperty(String key, String val) {
		conn.addRequestProperty(key, val);
	}

	public void release() {
		if (conn != null) {
			conn.disconnect();
		}
	}

	/**
	 * 获取返回数据
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	private String parsRtn(InputStream is) throws IOException {

		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuffer buffer = new StringBuffer();
		String line = null;
		boolean first = true;
		while ((line = reader.readLine()) != null) {
			if (first) {
				first = false;
			} else {
				buffer.append("\n");
			}
			buffer.append(line);
		}
		return buffer.toString();
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public WeixinPayClient addParam(String key, String val) {

		if (key != null && key.length() > 0) {
			params.add(key + "=" + val);
		}
		return this;
	}

	public static void main(String[] args) {
		try {
			// appkey=646c79aecc19&phone=15201967267&zone=86&code=1436
			Map<String, String> map = new HashMap<String, String>();
			map.put("appkey", "646c79aecc19");
			map.put("phone", "15201967267");
			map.put("zone", "86");
			map.put("code", "1436");
			HttpURLConnection[] tions = new HttpURLConnection[2];
			try {
				StringBuilder builder = new StringBuilder();
				for (String key : map.keySet()) {
					builder.append(key);
					builder.append("=");
					builder.append(map.get(key) + "&");
				}
				long now = System.currentTimeMillis();
				System.out.println(new Date(now));
				for (int i = 0; i < 300; i++) {
					WeixinPayClient client = new WeixinPayClient("https://api.sms.mob.com/sms/verify");

					String result = client.post(builder.toString().substring(0, builder.length() - 1));
					if (i == 100) {
						long now2 = System.currentTimeMillis();
						System.out.println(now2 - now);
					}
				}
				long now3 = System.currentTimeMillis();
				System.out.println(now3 - now);
			} catch (Throwable e) {
				e.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();

		}
	}
}
